/* ===================

AX2E (AXESCON XACML 2.0 Engine) is the Java authorization engine, which implements OASIS XACML 2.0 standard.
Copyright (C) 2007 AXESCON LLC

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA


Contact: AXESCON LLC - info{at}axescon.com

 =================== */
package axescon.xacml.xb.ctx;

import axescon.xacml.api.ResponseSerializer;
import axescon.xacml.model.ctx.*;
import axescon.xacml.model.policy.Obligation;
import org.apache.xmlbeans.XmlOptions;
import x0ContextSchemaOs.oasisNamesTcXacml2.*;
import x0PolicySchemaOs.oasisNamesTcXacml2.ObligationsType;

import java.io.OutputStream;

/**
 * @author argyn
 *         Date: Sep 19, 2005
 *         Responsibilities: serialize AXESCON XACML Model Response object into XML stream
 */
public class XBResponseSerializer implements ResponseSerializer {

    public void writeResponse(OutputStream os, Response resp) throws Exception {
        ResponseDocument rd = ResponseDocument.Factory.newInstance();

        rd.setResponse(toResponseType(resp));

        XmlOptions options = new XmlOptions();
        options.setSavePrettyPrint();
        options.setSavePrettyPrintIndent(4);

        rd.save(os, options);
    }

    private ResponseType toResponseType(Response resp) throws Exception {
        ResponseType ret = ResponseType.Factory.newInstance();
        ret.setResultArray(toResultArray(resp.getResultArray()));

        return ret;
    }

    private ResultType[] toResultArray(Result[] rs) throws Exception {
        if (rs == null || rs.length == 0) return null;

        ResultType[] ret = new ResultType[rs.length];
        for (int i = 0; i < rs.length; i++) {
            ret[i] = toResulType(rs[i]);
        }
        return ret;
    }


    public ResultType toResulType(Result res) throws Exception {
        if (res == null) return null;

        ResultType ret = ResultType.Factory.newInstance();
        ret.setResourceId(res.getResourceId());
        ret.setDecision(DecisionType.Enum.forString(res.getDecisionString()));
        if (res.getObligationList() != null) {
            ret.setObligations(ObligationsType.Factory.newInstance());
            ret.getObligations().setObligationArray(getXbObligationSerializer()
                    .toObligationTypeArray(
                    (Obligation[]) res.getObligationList().toArray(
                            new Obligation[res.getObligationList().size()]), null));
        }
        ret.setStatus(toStatus(res.getStatus()));
        return ret;
    }

    public StatusType toStatus(Status status) throws Exception {
        if (status == null) return null;

        StatusType ret = StatusType.Factory.newInstance();
        ret.setStatusCode(toStatusCode(status.getStatusCode()));
        ret.setStatusDetail(toStatusDetail(status.getStatusDetail()));
        ret.setStatusMessage(status.getStatusMessage());
        return ret;
    }

    public StatusCodeType toStatusCode(StatusCode sc) throws Exception {
        if (sc == null) return null;

        StatusCodeType ret = StatusCodeType.Factory.newInstance();
        ret.setStatusCode(toStatusCode(sc.getStatusCode()));
        ret.setValue(sc.toString());
        return ret;
    }

    public StatusDetailType toStatusDetail(StatusDetail sd) throws Exception {
        if (sd == null) return null;

        StatusDetailType ret = StatusDetailType.Factory.newInstance();
        //TODO: implementation complete
        return ret;
    }


    private XBObligationSerializer xbObligationSerializer;

    public XBObligationSerializer getXbObligationSerializer() {
        return xbObligationSerializer;
    }

    public void setXbObligationSerializer(XBObligationSerializer xbObligationSerializer) {
        this.xbObligationSerializer = xbObligationSerializer;
    }

    public XBResponseSerializer(XBObligationSerializer xbObligationSerializer) {
        this.xbObligationSerializer = xbObligationSerializer;
    }

    public XBResponseSerializer(boolean setDefaults) {
        if (setDefaults) setDefaults();
    }

    public XBResponseSerializer() {
        this(false);
    }

    public void setDefaults() {
        setXbObligationSerializer(new XBObligationSerializer());
    }


}
